package cn.apelx.order.service;

import cn.apelx.api.store.service.StoreDubboService;
import cn.apelx.order.domain.Orders;
import cn.apelx.order.repository.OrdersRepository;
import cn.apelx.tcc.common.domain.ResultHolder;
import cn.apelx.tcc.common.domain.TccTransaction;
import cn.apelx.tcc.common.repository.TccTransactionRepository;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Optional;

/**
 * 订单
 *
 * @author apelx
 * @since 2022-05-02
 */
@Component
public class OrderServiceImpl implements OrderService {

    @DubboReference
    private StoreDubboService storeDubboService;

    @Autowired
    private OrdersRepository ordersRepository;

    @Autowired
    private TccTransactionRepository tccTransactionRepository;


    /**
     * spring @Transactional 需要在 @GlobalTransaction 注解内部
     */
//    @Transactional(rollbackFor = Exception.class) 加事务，tccTransaction保存会被回滚
    @Override
    public void createTcc(BusinessActionContext actionContext, String orderName, BigDecimal orderPrice) {

        // 先生成tcc事务控制记录,状态为try
        String xid = TccTransaction.genXid(actionContext.getXid(), actionContext.getActionContext());
        Optional<TccTransaction> tccOptional = tccTransactionRepository.findById(xid);
        TccTransaction tccTransaction = tccOptional.orElseGet(() -> {
            // 防悬挂
            TccTransaction tccTransaction1 = new TccTransaction(xid, TccTransaction.Status.INIT);
            tccTransactionRepository.save(tccTransaction1);
            return tccTransaction1;
        });
        // 如果先执行了rollback,这里是空try 防悬挂
        if (!tccTransaction.commit()) {
            return;
        }


        // 减库存
        String storeId = "store-id-002";
        storeDubboService.subStoreTcc(null, storeId, new BigDecimal("1"));

        // 生成订单
        Orders orders = new Orders("订单" + orderName, orderPrice);
        ordersRepository.save(orders);

        // TODO 能放进去，但是传不到rollback里去
        actionContext.getActionContext().put("orderId", orders.getId());
        System.err.println("createTcc...actionContextMap: " + actionContext.getActionContext());


        ResultHolder.put(actionContext.getXid(), orders.getId());

        System.out.println(10 / 0);
    }

    @Override
    public void createTccCommit(BusinessActionContext actionContext) {

    }

    @Override
    public void createTccRollback(BusinessActionContext actionContext) {

        System.err.println("createTccRollback ... actionContextMap: " + actionContext.getActionContext());

        String orderId = (String) ResultHolder.get(actionContext.getXid());
        System.err.println("createTccRollback ... orderId:" + orderId);

        // 找到这次事务记录的数据
        String xid = TccTransaction.genXid(actionContext.getXid(), actionContext.getActionContext());
        Optional<TccTransaction> optionalTcc = tccTransactionRepository.findById(xid);
        TccTransaction tccTransaction = optionalTcc.orElseGet(() -> {
            // 不存在就new一个，防悬挂(rollback比try先执行)
            TccTransaction tccTransaction1 = new TccTransaction(xid, TccTransaction.Status.ROLLED_BACKED);
            tccTransactionRepository.save(tccTransaction1);
            return tccTransaction1;
        });
        // 没有这次事务记录或已回滚过 则空回滚
        if (!tccTransaction.rollback()) {
            return;
        }

        Optional<Orders> optional = ordersRepository.findById(orderId);
        optional.ifPresent(orders -> {
            ordersRepository.delete(orders);
        });
        tccTransactionRepository.save(tccTransaction);
    }
}
